
#include "array.h"
#include "dynamic_array.h"
#include "utils.h"

template<class T>
class Buffer{
public:
    int size;

private:
    DynamicArray<T>* buf;

    void reserve(int reqSize){
        if (reqSize > buf->size){
            reqSize = (reqSize * 11 + 10) / 10;
            DynamicArray<T>* newBuf = new DynamicArray<T>(reqSize);
            Utils::move(*newBuf, 0, *buf, 0, size);
            delete buf;
            buf = newBuf;
        }
    }

public:
    Buffer(int capacity = 1)
    :   buf(0), size(0){
        if (capacity < 1){
            capacity = 1;
        }
        buf = new DynamicArray<T>(capacity);
        ASSERT(buf != 0, "no memory");
    }

    ~Buffer(){
        ASSERT(buf != 0, "internal error");
        delete buf;
        buf = 0;
    }

    const DynamicArray<T> array() const{
        DynamicArray<T> arr(size);
        Utils::move(arr, 0, *buf, 0, size);
        return arr;
    }

    void append(const Array<T>& data){
        int dataSize = data.size;

        int reqSize = size + dataSize;
        reserve(reqSize);
        Utils::move(*buf, size, data, 0, dataSize);
        size = reqSize;
    }

    void append(const T data[], const int dataSize){
        ASSERT(dataSize >= 0, "data size is invalid");

        int reqSize = size + dataSize;
        reserve(reqSize);
        Utils::move(*buf, size, data, dataSize);
        size = reqSize;
    }

    T& operator[](const int i){
        ASSERT(i < size, "index is invalid");
        return (*buf)[i];
    }

    const T& operator[](const int i) const{
        ASSERT(i < size, "index is invalid");
        return (*buf)[i];
    }

};

